#include <deque>
#include <vector>
#include <string>
#include <algorithm>
#include <exception>
#include <map>

// dvp: boo, is there no clever way to implement unions with strings
// as members?

typedef int AttributeType;

using std::string;
using std::vector;
using std::deque;
using std::sort;

class DiGrEdge;
class DiGrNode;

class DiGrNode {

 private:
  // vector to store pointers to associated edges in
  vector<DiGrEdge*> _inEdges;
  vector<DiGrEdge*> _outEdges;
  std::map<std::string, AttributeType> _attributes;
  
public:
  DiGrNode();

  void setAttribute(string attrName, AttributeType attrValue);
  AttributeType getAttribute(string attrName);

  void addInEdge(DiGrEdge *e);
  void addOutEdge(DiGrEdge *e);

  DiGrEdge* getInEdge(int index);
  DiGrEdge* getOutEdge(int index);

  DiGrNode* getParent(int index);
  DiGrNode* getChild(int index);

  int InEdges();
  int OutEdges();
  // int Parents();
  // int Children();

};

class DiGrEdge {
 private:
  // pointers to nodes
  DiGrNode* _inNode;
  DiGrNode* _outNode;
  // hashmap of attributes
  std::map<std::string, AttributeType> _attributes;

public:
  DiGrEdge();
  DiGrEdge(DiGrNode* fromNode, DiGrNode* toNode, bool Uedge = false);
  // attribute setters and accessors
  DiGrNode* inNode();
  DiGrNode* outNode();

  void setAttribute(string attrName, AttributeType attrValue);
  AttributeType getAttribute(string attrName);

};

enum AddByObject {ADDBY_NODE, ADDBY_EDGE};
enum AddByOrder {ASCENDING, DESCENDING};
enum AddByWhere {BACK, FRONT};

void DiGrAddBy(DiGrNode *current, deque<DiGrNode*> *queue, AddByWhere addWhere, AddByObject addObj, string property, AddByOrder order, int max);
